package com.wish233.wiliwilivideo.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wish233.wiliwilivideo.domain.dto.history.CreateOrUpdateHistory;
import com.wish233.wiliwilivideo.domain.po.Video;
import com.wish233.wiliwilivideo.domain.po.VideoViewHistory;
import com.wish233.wiliwiliapi.domain.vo.VideoVO;
import com.wish233.wiliwilivideo.domain.vo.VideoViewHistoryVO;
import com.wish233.wiliwilivideo.mapper.VideoViewHistoryMapper;
import com.wish233.wiliwilivideo.mq.MqProducer;
import com.wish233.wiliwilivideo.service.VideoService;
import com.wish233.wiliwilivideo.service.VideoViewHistoryService;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.wish233.wiliwilicommon.constants.RedisConstants.*;

/**
 * @author WHH
 * @description 针对表【video_view_history(视频观看历史表)】的数据库操作Service实现
 * @createDate 2025-03-28 14:11:52
 */
@Service
public class VideoViewHistoryServiceImpl extends ServiceImpl<VideoViewHistoryMapper, VideoViewHistory>
        implements VideoViewHistoryService {

    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private VideoService videoService;
    @Resource
    private MqProducer mqProducer;

    @Override
    public Boolean addOrUpdateHistory(CreateOrUpdateHistory createOrUpdateHistory) {
        //存Redis异步存MySQL
        VideoViewHistory videoViewHistory = BeanUtil.copyProperties(createOrUpdateHistory, VideoViewHistory.class);
        //根据userid和videoid查id
        //在Redis的zset中存观看的视频ID和时间戳 在hash结构里面存观看的时间
        //迭代方案：Redis中的数据只存2天内看过的，当用户播放视频时如果在Redis内直接跳转播放
        //MySQL实现分页查询历史记录，7天后自动删除
        String key = HISTORY_VIDEO_KEY + videoViewHistory.getUserId();
        String playTimeKey = HISTORY_VIDEO_TIME_KEY
                + videoViewHistory.getUserId() + ":"
                + videoViewHistory.getVideoId();
        VideoViewHistory get = getOne(new QueryWrapper<VideoViewHistory>()
                .eq("video_id", videoViewHistory.getVideoId())
                .eq("user_id", videoViewHistory.getUserId())
        );
        if (get == null) {
            save(videoViewHistory);
        } else {
            videoViewHistory.setId(get.getId());
        }
        videoViewHistory.setUpdateTime(new Date());
        stringRedisTemplate.opsForZSet()
                .add(key,
                        videoViewHistory.getId().toString(),
                        videoViewHistory.getUpdateTime().getTime());
        stringRedisTemplate.opsForValue()
                .set(playTimeKey, videoViewHistory.getPlayTime().toString(),
                        HISTORY_VIDEO_TTL, TimeUnit.DAYS);
        stringRedisTemplate.expire(key, HISTORY_VIDEO_TTL, TimeUnit.DAYS);
        // 异步同步到MySQL
        mqProducer.sendHistoryMessage(videoViewHistory);
        return true;
    }

    @Override
    public Long getVideoViewTime(Long videoId) {
        //获取用户id
        String userId = (String) StpUtil.getLoginId();
        //去Redis查
        String playTimeKey = HISTORY_VIDEO_TIME_KEY
                + userId + ":"
                + videoId;
        String time = stringRedisTemplate.opsForValue().get(playTimeKey);
        if (StrUtil.isBlank(time)) {
            return 0L;
        }
        return Long.parseLong(time);
    }

    @Override
    public List<VideoViewHistoryVO> listVideoViewVO(Long userId, int current, int pageSize) {
        Page<VideoViewHistory> page = page(new Page<>(current, pageSize),
                new QueryWrapper<VideoViewHistory>().eq("user_id", userId));
        return page.getRecords().stream().map(videoViewHistory -> {
            Long videoId = videoViewHistory.getVideoId();
            if (videoId == null) {
                return null;
            }
            VideoViewHistoryVO videoViewHistoryVO = BeanUtil.copyProperties(videoViewHistory, VideoViewHistoryVO.class);
            Video video = videoService.getById(videoId);
            if (video == null) {
                return null;
            }
            VideoVO videoVO = BeanUtil.copyProperties(video, VideoVO.class);
            videoViewHistoryVO.setVideoVO(videoVO);
            return videoViewHistoryVO;
        }).filter(Objects::nonNull).collect(Collectors.toList());
    }
}




